/* global module:true */
/* global require:true */

module.exports = function(grunt) {
  // load all grunt tasks
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

  var mods = [
    'common',
    'channel',
    'component',
    'content',
    'login',
    'my',
    'page',
    'setting'
  ];

  var assets = [
    'css',
    'font',
    'img',
    'js'
  ];

  function configJSHint(presets) {
    var cfg = presets || {};

    cfg.options = {
      jshintrc: true
    };

    mods.forEach(function (mod) {
      cfg[mod] = ['src/app/' + mod + '/**/*.js'];
    });

    return cfg;
  }

  function configQUnit(presets) {
    var cfg = presets || {};

    cfg.options = {
      '--web-security': 'no',
      coverage: {
        src: ['src/app/**/*.js'],
        instrumentedFiles: 'temp/',
        lcovReport: 'report/',
        linesThresholdPct: 85
      }
    };

    mods.forEach(function (mod) {
      cfg[mod] = ['test/' + mod + '/**/*.html'];
    });

    return cfg;
  }

  function configTransport(presets) {
    var cfg = presets || {};

    cfg.options = {
      debug: true,
      idleading: '',
      alias: '<%= pkg.spm.alias %>',
      paths: [
        'sea-modules'
      ]
    };

    mods.forEach(function (mod) {
      cfg[mod] = {
        files: [{
          expand: true,
          cwd: 'src/app/'+ mod + '/',
          src: [
            '**/*.js',
            '**/*.handlebars',
            '**/*.tpl',
            '!ace/**/*.js',
            '!editor/**/*.js',
            '!editor/tinymce/**/*.js'
          ],
          dest: '.build/app/'+ mod + '/'
        }]
      };
    });

    return cfg;
  }

  function configConcat(presets) {
    var cfg = presets || {};

    cfg.options = {
      debug: true,
      include: 'relative',
      paths: [
        'sea-modules'
      ]
    };

    mods.forEach(function (mod) {
      cfg[mod] = {
        files: [{
          expand: true,
          cwd: '.build/app/' + mod + '/',
          src: ['**/*.js'],
          dest: '../dist/app/' + mod + '/'
        }]
      };
    });

    return cfg;
  }

  function configUglify(presets) {
    var cfg = presets || {};

    cfg.options = {
      banner: '/*! <%= pkg.name %>-<%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %> */\n',
      beautify: {
        'ascii_only': true
      },
      compress: {
        'global_defs': {
          'DEBUG': false
        },
        'dead_code': true
      }
    };

    mods.forEach(function (mod) {
      cfg[mod] = {
        files: [{
          expand: true,
          cwd: '../dist/app/' + mod + '/',
          src: ['**/*.js', '!**/*-debug.js'],
          dest: '../dist/app/' + mod + '/'
        }]
      };
    });

    assets.forEach(function (asset) {
      cfg[asset] = {
        files: [{
          expand: true,
          cwd: '../dist/' + asset + '/',
          src: ['**/*.js', '!**/*-debug.js'],
          dest: '../dist/' + asset + '/'
        }]
      };
    });

    return cfg;
  }

  function configClean(presets) {
    var cfg = presets || {};

    cfg.options = {
      force: true
    };

    mods.forEach(function (mod) {
      cfg[mod] = {
        src: [
          '.build/app/' + mod + '/',
          '../dist/app/' + mod + '/'
        ]
      };
      cfg[mod + '-after'] = {
        src: [
          '.build/app/' + mod + '/'
        ]
      };
    });

    assets.forEach(function (asset) {
      cfg[asset] = {
        src: [
          '../dist/' + asset + '/'
        ]
      };
    });

    return cfg;
  }

  function configCopy(presets) {
    var cfg = presets || {};

    assets.forEach(function (asset) {
      cfg[asset] = {
        files: [{
          expand: true,
          cwd: 'src/' + asset + '/',
          src: [
            '**/*.gif',
            '**/*.png',
            '**/*.jpg',
            '**/*.eot',
            '**/*.svg',
            '**/*.ttf',
            '**/*.woff',
            '**/*.otf',
            '**/*.js',
            '**/cms.css',
            '**/login.css'
          ],
          dest: '../dist/' + asset + '/'
        }]
      };
    });

    return cfg;
  }

  function configLess(presets) {
    var cfg = presets || {};

    assets.forEach(function (asset) {
      var files = {};
      files['../dist/' + asset + '/cms.css'] = 'src/' + asset + '/cms/cms.less';
      files['../dist/' + asset + '/login.css'] = 'src/' + asset + '/cms/login.less';
      cfg[asset] = {
        options: {
          paths: ['src/css'],
          cleancss: true
        },
        files: files
      };
    });

    return cfg;
  }

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    fed: {
      task: {
        config: 'fed.json'
      }
    },

    exec: {
      editor: {
        cwd: './tinymce/',
        command: 'jake custom'
      }
    },

    watch: {
      concat: {
        files: ['src/app/**/*.js'],
        tasks: ['build']
      },
      design: {
        files: ['src/app/page/design/less/*.less'],
        tasks: ['less:design', 'wrap:design', 'clean:design']
      }
    },

    jshint: configJSHint({
      editor: [
        'src/app/common/editor/**/*.js',
        '!src/app/common/editor/tinymce/**/*.js'
      ]
    }),

    qunit: configQUnit(),

    coveralls: {
      options: {
        force: true
      },
      all: {
        src: 'report/*.info'
      }
    },

    uglify: configUglify({
      editor: {
        files: [{
          expand: true,
          cwd: '../dist/app/common/editor/',
          src: ['**/*.js', '!**/*-debug.js'],
          dest: '../dist/app/common/editor/'
        }]
      },
      ace: {
        files: [{
          expand: true,
          cwd: '../dist/app/common/ace/',
          src: ['**/*.js', '!**/*-debug.js'],
          dest: '../dist/app/common/ace/'
        }]
      }
    }),

    copy: configCopy({
      editor: {
        files: [{
          expand: true,
          cwd: 'tinymce/js/tinymce/dist/',
          src: ['*.*'],
          dest: 'src/app/common/editor/tinymce/'
        }, {
          expand: true,
          cwd: 'tinymce/js/tinymce/skins/pandora/css/',
          src: ['*.*'],
          dest: 'src/app/common/editor/tinymce/css/'
        }, {
          expand: true,
          cwd: 'tinymce/js/tinymce/skins/pandora/font/',
          src: ['*.*'],
          dest: 'src/app/common/editor/tinymce/font/'
        }, {
          expand: true,
          cwd: 'tinymce/js/tinymce/skins/pandora/img/',
          src: ['*.*'],
          dest: 'src/app/common/editor/tinymce/img/'
        }]
      },
      'editor-core': {
        files: [{
          expand: true,
          cwd: 'src/app/common/editor/tinymce/',
          src: ['**/*'],
          dest: '../dist/app/common/editor/tinymce/'
        }]
      },
      ace: {
        files: [{
          expand: true,
          cwd: 'src/app/common/ace/',
          src: ['**/*'],
          dest: '../dist/app/common/ace/'
        }]
      }
    }),

    transport: configTransport({
      editor: {
        files: [{
          expand: true,
          cwd: 'src/app/common/editor/',
          src: [
            '**/*.js',
            '**/*.handlebars',
            '**/*.tpl',
            '!tinymce/**/*.js'
          ],
          dest: '.build/app/common/editor/'
        }]
      }
    }),

    concat: configConcat({
      editor: {
        files: [{
          expand: true,
          cwd: '.build/app/common/editor/',
          src: ['**/*.js'],
          dest: '../dist/app/common/editor/'
        }]
      }
    }),

    clean: configClean({
      editor: {
        src: [
          '.build/app/common/editor/',
          '../dist/app/common/editor/'
        ]
      },
      'editor-after': {
        src: [
          '.build/app/common/editor/'
        ]
      },
      design: {
        src: ['src/app/page/design/less/*.css']
      },
      ace: {
        src: [
          '../dist/app/common/ace/'
        ]
      }
    }),

    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        options: {
          paths: 'src/app/',
          outdir: 'doc'
        }
      }
    },

    less: configLess({
      design: {
        options: {
          cleancss: true
        },
        files: {
          'src/app/page/design/less/worker.css': 'src/app/page/design/less/worker.less'
        }
      },
      cms: {
        options: {
          paths: ['src/css'],
          cleancss: true
        },
        files: {
          'src/css/login.css': 'src/css/login.less',
          'src/css/cms.css': 'src/css/cms.less'
        }
      }
    }),

    wrap: {
      design: {
        cwd: 'src/app/page/design/less/',
        expand: true,
        src: ['worker.css.tpl'],
        dest: 'src/app/page/design/',
        ext: '.css.js',
        options: {
          separator: '',
          // need a custom value to pass var
          csstext: 'src/app/page/design/less/worker.css',
          // compile (edit) content with function
          compiler: function(content, options) {
            var csstext = grunt.file.read(options.csstext);
            return content.replace(/@CSSTEXT/g,
              csstext.replace(/\\/g, '\\\\')
              .replace(/'/g, '\\\'').replace(/\n/g, ''));
          },
          wrapper: ['', '']
        }
      }
    }

  });

  // task for page design
  grunt.registerTask('design', [
    'less:design',
    'wrap:design',
    'clean:design',
    'watch:design'
  ]);

  grunt.registerTask('init-editor', [
    'exec:editor',
    'copy:editor'
  ]);

  grunt.registerTask('build-editor', [
    'copy:editor-core',
    'jshint:editor',
    'clean:editor',
    'transport:editor',
    'concat:editor',
    'uglify:editor'
  ]);

  grunt.registerTask('clean-editor', [
    'clean:editor-after'
  ]);

  grunt.registerTask('build-ace', [
    'clean:ace',
    'copy:ace',
    'uglify:ace'
  ]);

  mods.forEach(function(mod) {
    grunt.registerTask('build-mod-' + mod, [
      'jshint:' + mod,
      // 'qunit:' + mod,
      'clean:' + mod,
      'transport:' + mod,
      'concat:' + mod,
      'uglify:' + mod
    ]);
    grunt.registerTask('clean-mod-' + mod, [
      'clean:' + mod + '-after'
    ]);
  });

  grunt.registerTask('build-mod', mods.map(function (mod) {
    return 'build-mod-' + mod;
  }));

  grunt.registerTask('clean-mod', mods.map(function (mod) {
    return 'clean-mod-' + mod;
  }));

  assets.forEach(function(asset) {
    grunt.registerTask('asset-' + asset, [
      'clean:' + asset,
      'copy:' + asset,
      'less:' + asset,
      'uglify:' + asset
    ]);
  });

  grunt.registerTask('build-asset', assets.map(function (asset) {
    return 'asset-' + asset;
  }));

  grunt.registerTask('build', ['build-asset', 'build-mod', 'build-editor', 'build-ace', 'clean-mod']);

  grunt.registerTask('default', ['build', 'editor', 'watch', 'fed']);

};
